package com.atguigu.tingshu.album.service.impl;

import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackStatMapper;
import com.atguigu.tingshu.album.service.TrackInfoService;
import com.atguigu.tingshu.album.service.VodService;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.album.TrackStat;
import com.atguigu.tingshu.query.album.TrackInfoQuery;
import com.atguigu.tingshu.user.client.UserInfoFeignClient;
import com.atguigu.tingshu.vo.album.*;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class TrackInfoServiceImpl extends ServiceImpl<TrackInfoMapper, TrackInfo> implements TrackInfoService {


    @Autowired
    private TrackInfoMapper trackInfoMapper;

    @Resource
    private VodService vodService;
    @Resource
    private AlbumInfoMapper albumInfoMapper;
    @Resource
    private TrackStatMapper trackStatMapper;

    @Resource
    private UserInfoFeignClient userInfoFeignClient;

    /**
     * 批量获取下单付费声音列表
     * @param trackId
     * @param trackCount
     * @param userId
     * @return
     */
    @Override
    public List<TrackInfo> findPaidTrackInfoList(Long trackId, Integer trackCount, Long userId) {
        //  声明一个集合；
        List<TrackInfo> trackInfoList = new ArrayList<>();
        //  1.  获取用户购买过的声音列表;
        //  通过声音Id获取到声音对象中的专辑Id
        TrackInfo trackInfo = this.getById(trackId);
        Result<List<Long>> userPaidTrackList = userInfoFeignClient.findUserPaidTrackList(trackInfo.getAlbumId());
        //  判断返回数据集
        Assert.notNull(userPaidTrackList, "查询用户购买声音列表失败");
        //  这个集合可以为空.
        List<Long> userPaidTrackIdList = userPaidTrackList.getData();

        //  判断当前购买的集数;
        if (0 == trackCount) {
            //  购买的是本集；
            trackInfoList.add(trackInfo);
        } else {
            //  设置查询条件;
            LambdaQueryWrapper<TrackInfo> wrapper = new LambdaQueryWrapper<>();
            wrapper.gt(TrackInfo::getOrderNum, trackInfo.getOrderNum())
                    .eq(TrackInfo::getAlbumId, trackInfo.getAlbumId());
            if (!CollectionUtils.isEmpty(userPaidTrackIdList)) {
                //  排除用户已购买的声音Id;
                wrapper.notIn(TrackInfo::getId, userPaidTrackIdList);
            }
            wrapper.last(" limit " + trackCount);
            //  查询数据;
            trackInfoList = trackInfoMapper.selectList(wrapper);
        }
        //  返回数据;
        return trackInfoList;
    }

    /**
     * 获取用户声音购买列表
     * @param trackId
     * @param userId
     * @return
     */
    @Override
    public List<Map<String, Object>> findUserTrackPaidList(Long trackId, Long userId) {
         /*
        1.  从当前点击的声音开始，计算有多少需要付费的声音列表;
        2.  查询用户是否购买过当前专辑对应的声音，然后与1步骤进行过滤;
         */
        List<Map<String, Object>> list = new ArrayList<>();
        //  获取对象
        TrackInfo trackInfo = this.getById(trackId);
        //  获取当前声音Id的排序值;
        Integer orderNum = trackInfo.getOrderNum();
        //  获取到当前用户购买的声音列表；
        Result<List<Long>> trackIdListResult = userInfoFeignClient.findUserPaidTrackList(trackInfo.getAlbumId());
        Assert.notNull(trackIdListResult, "查询用户购买声音列表失败");
        List<Long> trackIdList = trackIdListResult.getData();

        //  从当前声音Id开始计算有多少声音是需要付费的集合Id;
        //  select * from track_info where order_num > 8 and album_id = 341;
        //  7--54  trackIdListResult {17,18,19}
        List<TrackInfo> trackInfoList = trackInfoMapper.selectList(new LambdaQueryWrapper<TrackInfo>()
                .eq(TrackInfo::getAlbumId, trackInfo.getAlbumId())
                .gt(TrackInfo::getOrderNum, orderNum));

        //  两个集合取差集,需要付费的声音列表;
        List<TrackInfo> paidTrackIdList = trackInfoList.stream().filter(trackInfoItem -> !trackIdList.contains(trackInfoItem.getId())).collect(Collectors.toList());
        //  根据专辑Id获取专辑对象
        AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfo.getAlbumId());
        //  判断
        if (paidTrackIdList.size() >= 0) {
            //  显示本集;
            HashMap<String, Object> map = new HashMap<>();
            map.put("name", "本集");
            //  当前每一集声音的钱数;
            map.put("price", albumInfo.getPrice());
            map.put("trackCount", 0);
            //  添加本集到集合;
            list.add(map);
        }
        //  后9集
        if (paidTrackIdList.size() > 0 && paidTrackIdList.size() <= 10) {
            //  显示后size集;
            HashMap<String, Object> map = new HashMap<>();
            map.put("name", "后" + paidTrackIdList.size() + "集");
            //  当前每一集声音的钱数;
            map.put("price", albumInfo.getPrice().multiply(new BigDecimal(String.valueOf(paidTrackIdList.size()))));
            map.put("trackCount", paidTrackIdList.size());
            //  添加本集到集合;
            list.add(map);
        }
        //  后10集;
        if (paidTrackIdList.size() > 10) {
            //  后10集合;
            HashMap<String, Object> map = new HashMap<>();
            map.put("name", "后10集");
            //  当前每一集声音的钱数;
            map.put("price", albumInfo.getPrice().multiply(new BigDecimal("10")));
            map.put("trackCount", 10);
            //  添加本集到集合;
            list.add(map);
        }

        //  后9集
        if (paidTrackIdList.size() > 10 && paidTrackIdList.size() <= 20) {
            //  显示后size集;
            HashMap<String, Object> map = new HashMap<>();
            map.put("name", "后" + paidTrackIdList.size() + "集");
            //  当前每一集声音的钱数;
            map.put("price", albumInfo.getPrice().multiply(new BigDecimal(String.valueOf(paidTrackIdList.size()))));
            map.put("trackCount", paidTrackIdList.size());
            //  添加本集到集合;
            list.add(map);
        }
        //  后10集;
        if (paidTrackIdList.size() > 20) {
            //  后10集合;
            HashMap<String, Object> map = new HashMap<>();
            map.put("name", "后20集");
            //  当前每一集声音的钱数;
            map.put("price", albumInfo.getPrice().multiply(new BigDecimal("20")));
            map.put("trackCount", 20);
            //  添加本集到集合;
            list.add(map);
        }
        //  返回数据
        return list;
    }

    /**
     * 更新声音统计数据
     *
     * @param trackStatMqVo
     */
    @Override
    public void updateTrackStat(TrackStatMqVo trackStatMqVo) {
        //更新声音的播放量;
        //判断是否是属于播放量：
        if (SystemConstant.TRACK_STAT_PLAY.equals(trackStatMqVo.getStatType())) {
            //  调用更新方法;
            trackInfoMapper.updateTrackStat(trackStatMqVo.getCount(), trackStatMqVo.getTrackId(), trackStatMqVo.getStatType());
            //更新专辑播放量；
            albumInfoMapper.updateAlbumStat(trackStatMqVo.getCount(), trackStatMqVo.getAlbumId(), SystemConstant.ALBUM_STAT_PLAY);
        }// 判断统计类型是否为收藏
        else if (SystemConstant.TRACK_STAT_COLLECT.equals(trackStatMqVo.getStatType())) {
            // 调用更新方法更新声音收藏量
            trackInfoMapper.updateTrackStat(trackStatMqVo.getCount(), trackStatMqVo.getTrackId(), trackStatMqVo.getStatType());
            // 更新专辑收藏量
            albumInfoMapper.updateAlbumStat(trackStatMqVo.getCount(), trackStatMqVo.getAlbumId(), SystemConstant.ALBUM_STAT_SUBSCRIBE);
        }
        // 判断统计类型是否为点赞
        else if (SystemConstant.TRACK_STAT_PRAISE.equals(trackStatMqVo.getStatType())) {
            // 调用更新方法更新声音点赞量
            trackInfoMapper.updateTrackStat(trackStatMqVo.getCount(), trackStatMqVo.getTrackId(), trackStatMqVo.getStatType());
            // 更新专辑点赞量
            albumInfoMapper.updateAlbumStat(trackStatMqVo.getCount(), trackStatMqVo.getAlbumId(), SystemConstant.ALBUM_STAT_BROWSE);
        }
        // 判断统计类型是否为评论
        else if (SystemConstant.TRACK_STAT_COMMENT.equals(trackStatMqVo.getStatType())) {
            // 调用更新方法更新声音评论量
            trackInfoMapper.updateTrackStat(trackStatMqVo.getCount(), trackStatMqVo.getTrackId(), trackStatMqVo.getStatType());
            // 更新专辑评论量
            albumInfoMapper.updateAlbumStat(trackStatMqVo.getCount(), trackStatMqVo.getAlbumId(), SystemConstant.ALBUM_STAT_COMMENT);
        }
    }

    /**
     * 分页查询专辑下的声音数据
     *
     * @param page
     * @param albumId
     * @param userId
     * @return
     */
    @Override
    public IPage<AlbumTrackListVo> findAlbumTrackPage(Page<AlbumTrackListVo> page, Long albumId, Long userId) {
        //获取专辑信息，查看是否付费，和免费试听的集数
        AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);
        //取出付费的集数
        Integer tracksForFree = albumInfo.getTracksForFree();

        //调用mapper根据专辑id查询声音列表
        IPage<AlbumTrackListVo> albumTrackListVoIPage = trackInfoMapper.selectAlbumTrackPage(page, albumId);
        //判断当前是否有用户登录
        if (null == userId) {
            //没有用户登录，如果没有则付费的专辑修改isShowPaidMark为true
            if (!albumInfo.getPayType().equals(SystemConstant.ALBUM_PAY_TYPE_FREE)) {
                //设计声音列表中集数大于tracksForFree的isShowPaidMark为true
                albumTrackListVoIPage.getRecords().stream().filter(
                        albumTrackListVo -> albumTrackListVo.getOrderNum() > tracksForFree
                ).forEach(albumTrackListVo -> albumTrackListVo.setIsShowPaidMark(true));
            }
        } else {
            //如果用户登录,先获取用户信息
            Result<UserInfoVo> userInfoVo = userInfoFeignClient.getUserInfoVo(userId);
            //断言
            Assert.notNull(userInfoVo, "远程获取用户信息失败");
            //获取用户信息
            UserInfoVo userInfoVoData = userInfoVo.getData();
            //断言
            Assert.notNull(userInfoVoData, "远程获取用户信息失败");

            //获取当前专辑下的呻吟id
            List<Long> trackIdList = albumTrackListVoIPage.getRecords().stream()
                    .filter(
                            albumTrackListVo -> albumTrackListVo.getOrderNum() > tracksForFree
                    ).collect(Collectors.toList())
                    .stream().map(AlbumTrackListVo::getTrackId).collect(Collectors.toList());

            //不管是不是vip，先判断用户是不是买了当前专辑,所以先判断当前专辑的付费模式
            //获取用户购买的声音,远程调用用户模块,获取用户购买的声音id的合集
            Result<List<Integer>> userPaidTrackIdList = userInfoFeignClient.getUserPaidTrack(albumId, trackIdList);
            //断言
            Assert.notNull(userPaidTrackIdList, "获取声音id失败");
            List<Long> userPaidTrackIdListData = userPaidTrackIdList.getData().stream()
                    .map(Integer::longValue)
                    .collect(Collectors.toList());
            Assert.notNull(userPaidTrackIdListData, "获取声音id失败");

            //System.out.println(userPaidTrackIdListData + "/////////////////////////////////////");

            //判断当前专辑的付费类型
            if (albumInfo.getPayType().equals(SystemConstant.ALBUM_PAY_TYPE_VIPFREE)) {
                //如果是vip免费，但是当前用户不是vip或vip过期，就判断当前购买的声音
                if (userInfoVoData.getIsVip() == 0 ||
                        (userInfoVoData.getIsVip() == 1 && userInfoVoData.getVipExpireTime().before(new Date()))) {
                    albumTrackListVoIPage.getRecords().stream()
                            .filter(albumTrackListVo -> !userPaidTrackIdListData.contains(albumTrackListVo.getTrackId()))
                            .forEach(albumTrackListVo -> albumTrackListVo.setIsShowPaidMark(true));

                }
                //恢复免费集数
                albumTrackListVoIPage.getRecords().stream()
                        .filter(albumTrackListVo -> albumTrackListVo.getOrderNum() <= tracksForFree)
                        .forEach(albumTrackListVo -> albumTrackListVo.setIsShowPaidMark(false));
            }
            //如果是付费类型，直接判断用户购买的声音列表就行
            if (albumInfo.getPayType().equals(SystemConstant.ALBUM_PAY_TYPE_REQUIRE)) {
                albumTrackListVoIPage.getRecords().stream()
                        .filter(albumTrackListVo -> !userPaidTrackIdListData.contains(albumTrackListVo.getTrackId()))
                        .forEach(albumTrackListVo -> albumTrackListVo.setIsShowPaidMark(true));

                albumTrackListVoIPage.getRecords().stream()
                        .filter(albumTrackListVo -> userPaidTrackIdListData.contains(albumTrackListVo.getTrackId()))
                        .forEach(albumTrackListVo -> albumTrackListVo.setIsShowPaidMark(false));

                //System.out.println("/**/*/*/*/*" + albumTrackListVoIPage.getRecords());
                //恢复没有免费集数
                albumTrackListVoIPage.getRecords().stream()
                        .filter(albumTrackListVo -> albumTrackListVo.getOrderNum() <= tracksForFree)
                        .forEach(albumTrackListVo -> albumTrackListVo.setIsShowPaidMark(false));
            }
        }
        return albumTrackListVoIPage;
    }

    /**
     * v
     *
     * @param trackId
     * @param trackInfoVo
     */
    @Override
    public void updateTrackInfo(Long trackId, TrackInfoVo trackInfoVo) {
        /**
         * 声音的修改，虽然只涉及track_info，但是当音频文件修改时，考虑修改云点播的文件
         */
        //根据trackid查询对应的旧的声音信息
        TrackInfo trackInfo = trackInfoMapper.selectById(trackId);
        //拷贝数据
        BeanUtils.copyProperties(trackInfoVo, trackInfo);
        System.out.println(trackInfo.toString());
        //如果更新了声音的话要更新文件的信息
        //获取新的fileid
        String newMediaFileId = trackInfoVo.getMediaFileId();
        //旧的id
        String oldMediaFileId = trackInfo.getMediaFileId();
        //如果不为空
        if (!StringUtils.isEmpty(newMediaFileId)) {
            //如果相等
            if (!newMediaFileId.equals(oldMediaFileId)) {
                //获取新的文件信息
                TrackMediaInfoVo mediaInfo = vodService.getMediaInfo(newMediaFileId);
                //给trackinfo赋值
                trackInfo.setMediaFileId(newMediaFileId);
                trackInfo.setMediaDuration(mediaInfo.getDuration());
                trackInfo.setMediaUrl(mediaInfo.getMediaUrl());
                trackInfo.setMediaSize(mediaInfo.getSize());
                trackInfo.setMediaType(mediaInfo.getType());
                //删除旧的文件
                vodService.delectFile(oldMediaFileId);
            }
        }
        //更新声音信息
        trackInfoMapper.updateById(trackInfo);
    }

    /**
     * 根据声音id删除声音
     *
     * @param trackId
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeTrackInfo(Long trackId) {
        /**
         * 声音的删除涉及到了三张表：track_info ，track_stat ，album_info
         */
        //根据trackid获取声音对象
        TrackInfo trackInfo = trackInfoMapper.selectById(trackId);
        //根据trackid查询专辑
        AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfo.getAlbumId());
        //删除track_info表的信息
        trackInfoMapper.deleteById(trackId);
        //根据trackid删除track_stat
        trackStatMapper.delete(new LambdaQueryWrapper<TrackStat>().eq(TrackStat::getTrackId, trackId));
        //调整album_info中的信息总个数
        albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount() - 1);
        //更新album_info表
        albumInfoMapper.updateById(albumInfo);

        //删除云点播上的声音
        vodService.delectFile(trackInfo.getMediaFileId());
    }

    /**
     * 分页查询声音数据
     *
     * @param page
     * @param trackInfoQuery
     * @return
     */
    @Override
    public IPage<TrackListVo> findUserTrackPage(Page<TrackListVo> page, TrackInfoQuery trackInfoQuery) {
        //调用mapper层的方法
        IPage<TrackListVo> trackListVoIPage = trackInfoMapper.selectUserTrackPage(page, trackInfoQuery);
        return trackListVoIPage;
    }

    /**
     * 保存声音
     *
     * @param trackInfoVo
     * @param userId      涉及三张表：track_info，track_stat，album_info
     */
    @Override
    public void saveTrackInfo(TrackInfoVo trackInfoVo, Long userId) {
        //封装track_info对应的队形
        TrackInfo trackInfo = new TrackInfo();
        //进行属性值拷贝
        BeanUtils.copyProperties(trackInfoVo, trackInfo);
        //赋值用户id
        trackInfo.setUserId(userId);
        //调用云点播的api获取声音的相关属性
        TrackMediaInfoVo trackMediaInfoVo = vodService.getMediaInfo(trackInfoVo.getMediaFileId());

        trackInfo.setMediaFileId(trackInfoVo.getMediaFileId());
        trackInfo.setMediaSize(trackMediaInfoVo.getSize());
        trackInfo.setMediaType(trackMediaInfoVo.getType());
        trackInfo.setMediaUrl(trackMediaInfoVo.getMediaUrl());
        trackInfo.setMediaDuration(trackMediaInfoVo.getDuration());

        //构建神声音的序号
        AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfoVo.getAlbumId());
        Integer includeTrackCount = albumInfo.getIncludeTrackCount();
        trackInfo.setOrderNum(includeTrackCount + 1);
        //保存信息表
        trackInfoMapper.insert(trackInfo);

        //操作track_stat表
        saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_PLAY);
        saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_COLLECT);
        saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_PRAISE);
        saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_PRAISE);

        //修改album_info的声音数量
        albumInfo.setIncludeTrackCount(trackInfo.getOrderNum());
        //更新
        albumInfoMapper.updateById(albumInfo);

    }

    /**
     * 保存状态表
     *
     * @param id
     * @param trackStatPlay
     */
    private void saveTrackStat(Long id, String trackStatPlay) {
        //创建track_stat对象
        TrackStat trackStat = new TrackStat();
        trackStat.setTrackId(id);
        trackStat.setStatType(trackStatPlay);
        trackStat.setStatNum(new Random().nextInt(1000));
        //保存
        trackStatMapper.insert(trackStat);
    }
}
